package org.xxpay.pay.channel.payeasepay;

import com.alibaba.fastjson.JSONObject;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.domain.api.msg.AgentPayBalanceRetMsg;
import org.xxpay.core.common.domain.api.msg.QueryRetMsg;
import org.xxpay.core.common.util.AmountUtil;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.BankCardBin;
import org.xxpay.core.entity.TransOrder;
import org.xxpay.pay.channel.BaseTrans;
import org.xxpay.pay.channel.payeasepay.demo.CFCA.MerchantX509Cert;
import org.xxpay.pay.channel.payeasepay.util.XmlUtils;
import org.xxpay.pay.mq.Mq4TransQuery;

import javax.ws.rs.core.MultivaluedMap;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Random;

@Service
public class PayeasepayTransService extends BaseTrans{

    private static final MyLog _log = MyLog.getLog(PayeasepayTransService.class);

    private final static String charset = "UTF-8";

    @Autowired
    private Mq4TransQuery mq4TransQuery;

    @Override
    public String getChannelName() { return PayeasepayConfig.CHANNEL_NAME_PAYEASEPAY; }

    @Override
    public String getTransOrderId(TransOrder transOrder) {
        // 对公
        if(transOrder.getAccountAttr() == 1) {
            return "B" + super.getTransOrderId(transOrder);
        }
        // 默认对私
        return "C" + super.getTransOrderId(transOrder);
    }

    /**
     * 代付申请
     *
     * */
    @Override
    public QueryRetMsg trans(TransOrder transOrder) {
        String logPrefix = "【首信易代付】";
        try {
            String transOrderId = transOrder.getTransOrderId();
            PayeasepayConfig payeasepayConfig = new PayeasepayConfig(getTransParam(transOrder));
            String reqUrl = payeasepayConfig.getReqUrl();	                                        // 接口地址
            String url = reqUrl + "/merchant/virement/mer_payment_submit_utf8.jsp";
            if (reqUrl.endsWith("/")){
                url = reqUrl + "merchant/virement/mer_payment_submit_utf8.jsp";
            }
            System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
            Client cc = Client.create();
            WebResource rr = cc.resource(url);
            MultivaluedMap queryParams = new MultivaluedMapImpl();

            String v_mid = payeasepayConfig.getV_mid();                                                 //商户编号
            String v_datas = getVdata(v_mid,transOrder);                                                //代付数据
            _log.info("{}生成代付数据内容为:{}", logPrefix, v_datas);
            String v_data = java.net.URLEncoder.encode(v_datas, "UTF-8");
            String v_mac;                                                                               //数字指纹
            String v_version = "1.0";                                                                   //版本号
            String pfxFile = getCertFilePath(getChannelName(), payConfig.getCertRootPath(), payeasepayConfig.getPfxFile());          //"D:/certificate/payease/cfca_private.pfx";
            String pfxPassword = payeasepayConfig.getPfxPassword();                                     //"lh121121";
            String aliasPassword = payeasepayConfig.getAliasPassword();                                 //"lh121121";
            String aliasName = payeasepayConfig.getAliasName();                                         //"{3dfcbb2d-bb3d-4350-9010-33de8cdb076c}";
            String beforeSignSrc = v_mid + v_data;
            v_mac = MerchantX509Cert.sign(beforeSignSrc, pfxFile, aliasName, pfxPassword, aliasPassword);

            queryParams.add("v_mid", v_mid);
            queryParams.add("v_data", java.net.URLEncoder.encode(v_datas, "GBK"));
            queryParams.add("v_version", v_version);
            queryParams.add("v_mac", v_mac);
            String ret = rr.queryParams(queryParams).post(String.class);
            Map<String,String> resultMap = XmlUtils.xml2Map(ret);

            if ("0".equals(resultMap.get("status"))){
                _log.info("{} >>> 转账中", logPrefix);

                JSONObject msgObj = new JSONObject();
                msgObj.put("count", 1);
                msgObj.put("transOrderId", transOrderId);
                msgObj.put("channelName", getChannelName());
                mq4TransQuery.send(msgObj.toJSONString(), 10 * 1000);  // 10秒后查询

                return QueryRetMsg.waiting();
            }else if ("1".equals(resultMap.get("status"))){
                _log.info("{} >>> 转账失败: {}", logPrefix, resultMap.get("statusdesc"));
                return QueryRetMsg.confirmFail();
            }else {
                _log.info("{} >>> 状态未知", logPrefix);
                return QueryRetMsg.unknown();
            }

        } catch (Exception e) {
            _log.error(e, "转账异常");
            return QueryRetMsg.sysError();
        }
    }

    /**
     * 代付状态查询
     *
     *
     * */
    public QueryRetMsg query(TransOrder transOrder) {
        String logPrefix = "【首信易代付查询】";
        QueryRetMsg retObj ;
        try {
            String transOrderId = transOrder.getTransOrderId();
            PayeasepayConfig payeasepayConfig = new PayeasepayConfig(getTransParam(transOrder));
            String reqUrl = payeasepayConfig.getReqUrl();                                            // 接口地址
            String url = reqUrl + "/merchant/virement/mer_payment_status_utf8.jsp";
            if (reqUrl.endsWith("/")) {
                url = reqUrl + "merchant/virement/mer_payment_status_utf8.jsp";
            }
            System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
            Client cc = Client.create();
            WebResource rr = cc.resource(url);
            MultivaluedMap queryParams = new MultivaluedMapImpl();

            String v_mid = payeasepayConfig.getV_mid();                                                 //商户编号
            String v_data = transOrderId;                                                               //客户标识
            String v_mac;                                                                               //数字指纹
            String v_version = "1.0";                                                                   //版本号
            String pfxFile = getCertFilePath(getChannelName(), payConfig.getCertRootPath(), payeasepayConfig.getPfxFile());          //私钥证书
            String pfxPassword = payeasepayConfig.getPfxPassword();                                     //证书
            String aliasPassword = payeasepayConfig.getAliasPassword();                                 //别名密码
            String aliasName = payeasepayConfig.getAliasName();                                         //别名
            String beforeSignSrc = v_mid + v_data;
            v_mac = MerchantX509Cert.sign(beforeSignSrc, pfxFile, aliasName, pfxPassword, aliasPassword);

            queryParams.add("v_mid", v_mid);
            queryParams.add("v_data", v_data);
            queryParams.add("v_version", v_version);
            queryParams.add("v_mac", v_mac);
            String ret = rr.queryParams(queryParams).post(String.class);
            Map<String, String> resultMap = XmlUtils.xml2Map(ret);
            _log.info("{}返回结果:{}", logPrefix, resultMap);
            String msg = resultMap.get("transdesc");
            if ("0".equals(resultMap.get("status")) || "2".equals(resultMap.get("status")) || "4".equals(resultMap.get("status"))) {
                _log.info("{} >>> 转账中", logPrefix);
                retObj = QueryRetMsg.waiting();
                retObj.setChannelOriginResponse(ret);
                return retObj;

            } else if ("1".equals(resultMap.get("status"))) {
                _log.info("{} >>> 转账成功: {}", logPrefix, resultMap.get("statusdesc"));
                retObj = QueryRetMsg.confirmSuccess(null);
                retObj.setChannelOriginResponse(ret);
                return retObj;

            }else if ("3".equals(resultMap.get("status"))) {
                _log.info("{} >>> 转账失败: {}", logPrefix, resultMap.get("statusdesc"));
                retObj = QueryRetMsg.confirmFail(null, null, msg);
                retObj.setChannelOriginResponse(ret);
                return retObj;

            } else if ("8".equals(resultMap.get("status"))) {
                _log.info("{} >>> 没有该用户标识对应的代付记录: {}", logPrefix, msg);
                retObj = QueryRetMsg.unknown();
                retObj.setChannelOriginResponse(ret);
                return retObj;


            } else if ("9".equals(resultMap.get("status"))) {
                _log.info("{} >>> 代付查询失败: {}", logPrefix, msg);
                retObj = QueryRetMsg.unknown();
                retObj.setChannelOriginResponse(ret);
                return retObj;

            } else {
                _log.info("{} >>> 转账失败", logPrefix);
                retObj = QueryRetMsg.unknown();
                retObj.setChannelOriginResponse(ret);
                return retObj;
            }
        } catch (Exception e) {
            _log.error(e, "首信易代付查询异常");
            return QueryRetMsg.sysError();
        }
    }

    /**
     * 代付余额查询
     *
     * */
    @Override
    public AgentPayBalanceRetMsg balance(String payParam) {
        String logPrefix = "【首信易代付余额查询】";
        try {
            PayeasepayConfig payeasepayConfig = new PayeasepayConfig(payParam);
            String reqUrl = payeasepayConfig.getReqUrl();	                                        // 接口地址
            String url = reqUrl + "/merchant/virement/mer_payment_balance_check.jsp";
            if (reqUrl.endsWith("/")){
                url = reqUrl + "merchant/virement/mer_payment_balance_check.jsp";
            }
            System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
            Client cc = Client.create();
            WebResource rr = cc.resource(url);
            MultivaluedMap queryParams = new MultivaluedMapImpl();

            String v_mid = payeasepayConfig.getV_mid();
            String pfxFile = getCertFilePath(getChannelName(), payConfig.getCertRootPath(), payeasepayConfig.getPfxFile());
            String pfxPassword = payeasepayConfig.getPfxPassword();
            String aliasPassword = payeasepayConfig.getAliasPassword();
            String aliasName = payeasepayConfig.getAliasName();
            String sign = MerchantX509Cert.sign(v_mid, pfxFile, aliasName, pfxPassword, aliasPassword);

            queryParams.add("v_mid", v_mid);
            queryParams.add("v_mac", sign);

            _log.info("{}开始余额查询,v_mid={}", logPrefix, v_mid);

            String ret = rr.queryParams(queryParams).post(String.class);
            Map<String,String> resultMap = XmlUtils.xml2Map(ret);
            _log.info("{}余额查询结果,v_mid={},resultMap={}", logPrefix, v_mid, resultMap);

            if (resultMap != null && "0".equals(resultMap.get("status")) ){
                String signSrc = resultMap.get("mid") + resultMap.get("balance");
                String v_sign = resultMap.get("sign");
                Boolean result = MerchantX509Cert.verifySign(signSrc, v_sign, getCertFilePath(getChannelName(), payConfig.getCertRootPath(), payeasepayConfig.pubkeyName));
                _log.info("{}Verify result: {}", logPrefix, result);
                if (result == true){

                    return AgentPayBalanceRetMsg.success(
                            Long.parseLong(AmountUtil.convertDollar2Cent(resultMap.get("balance"))), // 现金余额
                            Long.parseLong(AmountUtil.convertDollar2Cent(resultMap.get("balance"))) // 代付可用余额
                    );
                }
            }

            return AgentPayBalanceRetMsg.fail();
        } catch (Exception e) {
            _log.error(e, "查询余额异常");
            return AgentPayBalanceRetMsg.fail();
        }
    }

    private String getVdata(String v_mid, TransOrder transOrder) {

        String bankName = "招商银行";                                                                                    //开户行
        String bankNo = "102100099996";                                                                                 //联行号
        // 通过卡bin查询到银行卡信息
        BankCardBin bankCardBin = commonService.bankCardBinService.findByCardNo(transOrder.getAccountNo());
        if(bankCardBin != null && bankCardBin.getBankName() != null) {
            bankName = bankCardBin.getBankName().replace("\n","");
        }

        String dataCount = "1";                                                                                         //代付笔数
        String totalAmount = AmountUtil.convertCent2Dollar(transOrder.getAmount()+"");                                  //总金额
        String no = (System.nanoTime()+"").substring(6) + (new Random().nextInt(100)+"");
        String batchNo = v_mid + "-" + new SimpleDateFormat("yyyyMMdd").format(new Date())+ "-" + no;                   //批次号
        String accountNo = transOrder.getAccountNo();                                                                   //账户号
        String accountName = transOrder.getAccountName();                                                               //账户名
        String province = "北京市";                                                                                      //所在省
        String city = "北京市";                                                                                          //所在市
        /*String bankName = transOrder.getBankName();                                                                   //开户行
        String province = transOrder.getProvince();                                                                     //所在省
        String city = transOrder.getCity();                                                                             //所在市*/
        String amount = AmountUtil.convertCent2Dollar(transOrder.getAmount()+"");                                       //代付金额
        String transOrderId = transOrder.getTransOrderId();                                                             //客户标识

        StringBuffer v_data = new StringBuffer();
        v_data.append(dataCount);
        v_data.append("|" + totalAmount);
        v_data.append("|" + batchNo);
        v_data.append("$" + accountNo);
        v_data.append("|" + accountName);
        v_data.append("|" + bankName);
        v_data.append("|" + province);
        v_data.append("|" + city);
        v_data.append("|" + amount);
        v_data.append("|" + transOrderId);
        v_data.append("|" + bankNo);
        return v_data.toString();
    }


}
